package Server.junit;

import common.UserMap;
import common.UserMap.BoxType;

import Server.map.Box;
import Server.map.FightHappened;
import Server.map.Map;
import Server.players.Carnivorous;
import Server.players.Dino;
import Server.players.Herbivorous;
import Server.players.Player;
import junit.framework.TestCase;

public class MapTest extends TestCase {

	private Map m;
	protected void setUp() throws Exception {
		super.setUp();
		char[][] data = new char[40][40];
		/*
		 * PROVAAAAAAAAA MIA
		 */
		for (int i = 0;i < 40;i++)
			for (int j = 0;j < 40;j++)
				data[i][j] = 't';
		data[0][2] = 'a';
		data[1][2] = 'a';
		data[1][1] = 'a';
		data[2][2] = 'c';
		data[2][0] = 'v';
		
		this.m = new Map(null);
		//this.m.putDino(new Herbivorous(1), new Box(0, 1, false));
		/*
		 * Schema sul quaderno
		 */
	}

	protected void tearDown() throws Exception {
		super.tearDown();
	}

	public void testMap() {
		/* PROVA */
		assertNotNull(this.m);
	}

	/*public void testGenerateMap(){
		this.m = new Map(null);
		assertNotNull(this.m);
	}*/
	
	public void testGet() {
		Box b = new Box(1, 1, false);
		assertEquals(b, this.m.get(1, 1));
	}

	public void testGetRandomFreeBox() {
		Box b = this.m.getRandomFreeBox();
		assertNotNull(b);
		assertFalse(b.isWater());
		assertTrue(this.m.isFree(b));
	}

	public void testWalkable() {
		Box b1 = new Box(1, 1, false);
		Box b2 = new Box(2, 2, true);
		Dino d = new Carnivorous(2, new Box(1, 2, false));
		assertTrue(this.m.walkable(b1, d));
		assertFalse(this.m.walkable(b2, d));
	}

	public void testReachable() {
		Box b1 = new Box(2, 1, false);
		Box b2 = new Box(2, 2, true);
		Box b3 = new Box(10, 10, false);
		Dino d = new Herbivorous(1, new Box(0, 1, false));
		assertTrue(this.m.reachable(d, b1));
		assertFalse(this.m.reachable(d, b2));
		assertFalse(this.m.reachable(d, b3));
	}

	public void testComputeDistance() {
		Box b1 = this.m.get(0, 0);
		Box b2 = this.m.get(0, 1);
		Box b3 = this.m.get(2, 1);
		Box b4 = this.m.get(0, 3);
		// non raggiungibile, c'e l'altro dino
		assertTrue(this.m.computeDistance(b1, b2, new Herbivorous(1, b1)) > 40);
		
		assertTrue(this.m.computeDistance(b2, b3, new Herbivorous(1, b2)) == 2);
		assertTrue(this.m.computeDistance(b3, b4, new Herbivorous(1, b3)) == 3);
		assertTrue(this.m.computeDistance(b4, b3, new Herbivorous(1, b4)) == 3);
		assertTrue(this.m.computeDistance(b1, b3, new Herbivorous(1, b1)) == 2);
		// questa non e facile
		//Box b5 = this.m.get(1, 0);
		//assertTrue(this.m.computeDistance(b5, b4, new Herbivorous(1, b5)) == 4);
	}

	public void testGetUserMap() {
		UserMap m;
		Player p1 = new Player("pippo", "pluto");
		p1.newSpecies("spe", 'e');
		Dino d = p1.newDino(1);
		d.place(this.m.get(0, 1));
		m = this.m.getUserMap(p1);
		assertNotNull(m);
	}

	public void testGetDinoVisual() {
		UserMap m;
		Dino d = new Herbivorous(1, this.m.get(0, 1));
		m = this.m.getDinoVisual(new Player("pippo", "pluto"), d);
		int[] coord1 = {0, 0};
		assertTrue(m.typeOf(coord1).equals(BoxType.LAND));
		int[] coord2 = {1, 1};
		assertTrue(m.typeOf(coord2).equals(BoxType.WATER));
		int[] coord3 = {2, 2};
		assertTrue(m.typeOf(coord3).equals(BoxType.MEAT));
		assertTrue(this.m.get(2, 2).getFoodEnergy().equals(m.valueOf(coord3)));
		int[] coord4 = {2, 0};
		assertTrue(m.typeOf(coord4).equals(BoxType.VEGE));
		assertTrue(this.m.get(2, 0).getFoodEnergy().equals(m.valueOf(coord4)));
		int[] coord6 = {0, 1};
		assertTrue(m.typeOf(coord6).equals(BoxType.DINO));
		assertTrue(m.valueOf(coord6) == 1);
	}

	public void testUpdateFood() {
		int energy1 = this.m.get(2, 2).getFoodEnergy();
		int energy2 = this.m.get(2, 0).getFoodEnergy();
		this.m.updateFood();
		assertTrue(energy1 > this.m.get(2, 2).getFoodEnergy());
		assertTrue(energy2 <= this.m.get(2, 0).getFoodEnergy());
		this.m.get(2,0).foodEaten();
		energy2 = this.m.get(2, 0).getFoodEnergy();
		this.m.updateFood();
		assertTrue(energy2 <= this.m.get(2, 0).getFoodEnergy());
	}

	public void testPutDino() {
		Box b = this.m.get(3, 0);
		this.m.putDino(new Carnivorous(2), b);
		assertFalse(this.m.isFree(b));
	}

	public void testRemoveDino() {
		Dino d = new Herbivorous(1);
		this.m.removeDino(d);
		Box b = this.m.get(0, 1);
		assertTrue(this.m.isFree(b));
	}

	public void testMoveDino() {
		Dino d = new Herbivorous(1, this.m.get(0, 1));
		int energy = d.getEnergy();
		Box dest = this.m.get(2, 0);
		try{
			this.m.moveDino(d, dest);
			assertTrue(this.m.isFree(this.m.get(0, 1)));
			assertFalse(this.m.isFree(this.m.get(2, 0)));
			assertTrue(this.m.get(2, 0).getFoodEnergy() == 0);
			assertTrue(energy < d.getEnergy());
		} catch (FightHappened e){ // POI DEVO METTERE UN ALTRO DINO
			assertTrue(this.m.isFree(this.m.get(0, 1)));
			assertFalse(this.m.isFree(this.m.get(2, 0)));
			assertTrue(energy < d.getEnergy());
		}
	}

}
